<template>
	<view class="recorder">
		<view class="re-top" v-if="showTop">
			<view class="re-cancel" @click="cancel">取消</view>
			<view class="re-confirm" :style="{color: theme}" @click="confirm">{{ confirmText }}</view>
		</view>
		<text class="title">{{ finish ? '点击播放' : '长按录制语音' }}</text>
		<view class="recorder-box" v-if="!finish" @touchstart="onStartRecoder" @touchend="onEndRecoder">
			<ucircleprogress :active-color="theme" :duration="0" :percent="calcProgress">
				<view class="u-progress-content">
					<image src="/static/sound-recording/voice.png" :style="{ width: width, height: height }"></image>
				</view>
			</ucircleprogress>
		</view>
		<view class="recorder-box" v-else @click="playVoice">
			<ucircleprogress :active-color="theme" :duration="0" :percent="playProgress">
				<view class="u-progress-content">
					<image src="/static/sound-recording/play.png" :style="{ width: width, height: height }"
						v-if="!playStatus"></image>
					<image src="/static/sound-recording/pause.png" :style="{ width: width, height: height }" v-else>
					</image>
				</view>
			</ucircleprogress>
		</view>
		<text class="now-date">{{ reDate }}</text>
		<view style="color: #fff;" @click="reset">重新录制</view>
	</view>
</template>

<script>
import ucircleprogress from '../progress/progress.vue'

export default {
  components: {
    ucircleprogress
  },
  props: {
    width: {
      type: String,
      default: '60rpx'
    },
    height: {
      type: String,
      default: '60rpx'
    },
    showTop: {
      type: Boolean,
      default: true
    },
    maximum: {
      type: [Number, String],
      default: 15
    },
    duration: {
      type: Number,
      default: 20
    },
    theme: {
      type: String,
      default: '#5FBC94'
    },
    confirmText: {
      type: String,
      default: '发送'
    }
  },
  data() {
    return {
      reDate: '00:00',
      sec: 0,
      min: 0,
      finish: false,
      voicePath: '',
      playProgress: 100,
      playTimer: null,
      timer: null,
      playStatus: false,
      innerAudioContext: null,
      mediaRecorder: null,
      recordedChunks: [],
      pressTimer: null,
      pressStartTime: null,
      minRecordingDuration: 1, // 最小录音时长（秒）
    };
  },
  computed: {
    calcProgress() {
      return (this.sec + (this.min * 60)) / this.maximum * 100;
    }
  },
  methods: {
    confirm() {
      if (this.innerAudioContext) {
        this.innerAudioContext.pause();
      }
      this.$emit('confirm', this.voicePath,this.sec);
    },
    cancel() {
      if (this.innerAudioContext) {
        this.innerAudioContext.pause();
      }
      this.$emit('cancel');
    },
    handle() {
      this.$emit('click');
    },
    reset() {
      this.voicePath = '';
      this.min = 0;
      this.sec = 0;
      this.reDate = '00:00';
      this.playProgress = 100;
      this.finish = false;
      this.playStatus = false;

      if (this.innerAudioContext) {
        this.innerAudioContext.stop();
        this.innerAudioContext.destroy();
        this.innerAudioContext = null;
      }
      
      if (this.mediaRecorder) {
        this.mediaRecorder.stop();
        this.mediaRecorder = null;
      }

      this.recordedChunks = [];
      clearInterval(this.timer);
      this.timer = null;

      this.$emit('reset');
    },
    playVoice() {
      if (this.innerAudioContext) {
        if (this.innerAudioContext.paused) {
          this.innerAudioContext.play();
          this.playStatus = true;
        } else {
          this.innerAudioContext.pause();
          this.playStatus = false;
        }
        this.$emit('playVoice', this.innerAudioContext.paused);
      }
    },
    onEndRecoder() {
      clearTimeout(this.pressTimer); // 清除长按计时器
      if (this.mediaRecorder) {
        this.mediaRecorder.stop();
      }
    },
    onStartRecoder() {
      this.pressStartTime = Date.now();
      this.sec = 0; // 重置秒数
      this.min = 0; // 重置分钟
      this.startDate(); // 启动时间更新
      this.pressTimer = setTimeout(() => {
        navigator.mediaDevices.getUserMedia({ audio: true })
          .then(stream => {
            this.mediaRecorder = new MediaRecorder(stream);
            this.mediaRecorder.ondataavailable = event => {
              if (event.data.size > 0) {
                this.recordedChunks.push(event.data);
              }
            };
            this.mediaRecorder.onstop = () => {
              // 计算实际录音时间
              const recordingDuration = (Date.now() - this.pressStartTime) / 1000;
              if (recordingDuration < this.minRecordingDuration) {
                this.reset();
                uni.showToast({
                  title: '录音不足一秒！',
                  icon: 'none'
                });
                return;
              }

              this.voicePath = URL.createObjectURL(new Blob(this.recordedChunks, { type: 'audio/wav' }));
              this.recordedChunks = [];
              
              this.innerAudioContext = uni.createInnerAudioContext();
              this.innerAudioContext.src = this.voicePath;

              this.innerAudioContext.onEnded(() => {
                this.playStatus = false;
              });

              this.finish = true;
              clearInterval(this.timer);
              this.$emit('end');
            };
            this.mediaRecorder.start();
            this.$emit('start');
          })
          .catch(err => {
            console.error('Error accessing audio media:', err);
          });
      }, 500); // 长按0.5秒
    },
    startDate() {
      clearInterval(this.timer);
      this.timer = setInterval(() => {
        this.sec += this.duration / 1000;
        if (this.sec >= 60) {
          this.min++;
          this.sec = 0;
        }
        this.resetDate();
      }, this.duration);
    },
    resetDate() {
      let _s = this.sec < 10 ? '0' + Math.floor(this.sec) : Math.floor(this.sec);
      let _m = this.min < 10 ? '0' + this.min : this.min;
      this.reDate = _m + ':' + _s;
    }
  }
};
</script>



<style lang="scss">
	.recorder {
		position: fixed;
		top: 0;
		left: 0;
		height: 100vh;
		z-index: 99;
		display: flex;
		align-items: center;
		flex-direction: column;
		background-color: rgba(0,0,0,0.5);
		font-size: 24rpx;
		width: 100%;
		padding-bottom: 100rpx;

		.re-top {
			display: flex;
			justify-content: space-between;
			padding: 10rpx 20rpx;
			width: 100%;
			font-size: 28rpx;
			box-sizing: border-box;
			color: #fff;
		}

		.title {
			font-size: 36rpx;
			color: #fff;
			padding: 20rpx 0 30rpx;
		}

		.recorder-box {
			position: relative;
		}

		.now-date {
			font-size: 28rpx;
			color: #fff;
			padding: 20rpx 0;
		}
	}
</style>